package com.test.nnooolwdeaer.util_wooden.event

import android.annotation.SuppressLint
import android.util.Log
import com.google.gson.Gson
import com.test.nnooolwdeaer.activity_fragment_wooden.base_wooden.BaseApplication_wooden
import com.test.nnooolwdeaer.constant_wooden.Constant_wooden
import com.test.nnooolwdeaer.util_wooden.http_wooden.HttpManager_wooden
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import org.json.JSONArray
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.coroutines.coroutineContext

/**
 * ============================
 *  TODO: TrackManager: 埋点管理器
 * ============================
 */
@SuppressLint("StaticFieldLeak")
object TrackManager_wooden {

    private lateinit var repo: TrackEventRepository_wooden

    // Coroutine Scope
    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())

    /** 上传操作的互斥锁 */
    private val uploadMutex = Mutex()

    /** 任务间隔 */
    private var uploadIntervalMillis: Long = 5000L

    /** 定时上传任务的状态 */
    private val isUploadingScheduled = AtomicBoolean(false)

    /** 释放任务的状态 */
    private var isDestroyed = AtomicBoolean(false)

    /** 当前在上传的任务 */
    private var currentUploadJob: Job? = null

    /** 初始化方法 */
    fun init() {
        this.repo = TrackEventRepository_wooden(BaseApplication_wooden.getApplication())
    }

    /** 设置定时间隔 */
    fun setUploadInterval(intervalMillis: Long) {
        uploadIntervalMillis = intervalMillis
    }

    /** 停止定时上传任务 */
    fun stopScheduledUpload() {
        isUploadingScheduled.set(false)
    }

    /** 释放 */
    fun destroy() {
        if (isDestroyed.compareAndSet(false, true)) {
            stopScheduledUpload()
            scope.cancel()
            repo.close()
        }
    }

    /** 记录埋点事件 */
    fun track(type: String, remark: String) {
        scope.launch(Dispatchers.IO) {
            try {
                repo.insertEvent(TrackEvent_wooden(type = Constant_wooden.PRODUCT_wooden+"_"+type, remark = remark))
                if (Constant_wooden.Debug) Log.d("TrackManager", "Event recorded: $type")
            } catch (e: Exception) {
                if (Constant_wooden.Debug) e.printStackTrace()
            }
        }
    }

    /** 记录埋点事件，并立即上传 */
    fun trackNow(type: String, remark: String) {
        scope.launch(Dispatchers.IO) {
            try {
                repo.insertEvent(TrackEvent_wooden(type = Constant_wooden.PRODUCT_wooden+"_"+type, remark = remark))
                if (Constant_wooden.Debug) Log.d("TrackManager", "Event recorded: $type")
                performUpload()
            } catch (e: Exception) {
                if (Constant_wooden.Debug) e.printStackTrace()
            }
        }
    }

    /** 主动上传未上传的埋点事件 */
    fun uploadEvents() {
        scope.launch(Dispatchers.IO) {
            try {
                if (!isActive) return@launch
                performUpload()
            } catch (e: Exception) {
                if (Constant_wooden.Debug) e.printStackTrace()
            }
        }
    }

    /** 删除已上传的埋点事件 */
    fun deleteEvents(){
        scope.launch(Dispatchers.IO) {
            try {
                repo.deleteUploadedEvents()
                if (Constant_wooden.Debug) Log.d("TrackManager", "Delete recorded")
                performUpload()
            } catch (e: Exception) {
                if (Constant_wooden.Debug) e.printStackTrace()
            }
        }
    }

    /** 通用的上传逻辑 */
    private suspend fun performUpload() {
        try {
            currentUploadJob?.cancel()
            if (!coroutineContext.isActive) return

            uploadMutex.withLock {
                if (!coroutineContext.isActive) return

                val eventsToUpload = repo.getUnUploadedEvents()
                if (eventsToUpload.isNotEmpty()) {
                    currentUploadJob = scope.launch(Dispatchers.IO) {
                        try {
                            val jsonArray = JSONArray(Gson().toJson(eventsToUpload))
                            HttpManager_wooden.getInstance_wooden().uploadUSerBuriedPoint(jsonArray) {
                                try {
                                    val ids = eventsToUpload.map {
                                        (it["id"] ?: "0").toLong()
                                    }
                                    println(ids)
                                    repo.markAsUploaded(ids)
                                }catch (e: java.lang.Exception){
                                    if (Constant_wooden.Debug) e.printStackTrace()
                                }
                            }
                        } catch (e: Exception) {
                            if (Constant_wooden.Debug) e.printStackTrace()
                        }
                    }
                }
            }
        } catch (e: Exception) {
            if (Constant_wooden.Debug) e.printStackTrace()
        }
    }
}
